﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;

using System.ServiceModel.DomainServices.Client;

using System.Collections.ObjectModel;

using System.IO;
using System.IO.IsolatedStorage;

using LEEAAttendanceControl;
using LEEAAttendanceControl.Web;
using LEEAAttendanceControl.General;
using LEEAAttendanceControl.Web.Services;

using LEEAAttendanceControl.AttendanceReference;

using System.ServiceModel;

using System.Windows.Browser;

using System.ComponentModel;
using System.Threading;
using System.Globalization;

namespace LEEAAttendanceControl.Views
{
    public partial class MainView : Page
    {
        LEEAContext context = new LEEAContext();

        public MainView()
        {
            InitializeComponent();
            Thread.CurrentThread.CurrentCulture = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();
            Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy";
        }

        // Executes when the user navigates to this page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            welcomeText.Text = "Welcome : " + ((App)Application.Current).UserName;

            GetAttendanceStatistics();

            App myApp = (App)Application.Current;

            myApp.PeriodFrom = General.General.FirstDayOfCurrentMonth();
            myApp.PeriodTo = DateTime.Now;

            PeriodFrom.Text = myApp.PeriodFrom.ToShortDateString();
            PeriodTo.Text = myApp.PeriodTo.ToShortDateString();

            myApp.ClearEvents();

            myApp.ReloadTree += ReloadTreeHandler;
          
            myApp.AddCompanyEvent += NewCompanyHandler;
            myApp.EditCompanyEvent += EditCompanyHandler;
            myApp.DeleteCompanyEvent += DeleteCompanyHandler;

            myApp.AddDepartmentEvent += NewDepartmentHandler;
            myApp.EditDepartmentEvent += EditDepartmentHandler;
            myApp.DeleteDepartmentEvent += DeleteDepartmentHandler;

            myApp.RefreshAttendanceStatistics += RefreshStatisticsHandler;
        }

        //====================================================================
        //--> Event Handlers for User Logout:

        private void hyperLogout_Click(object sender, RoutedEventArgs e)
        {
            InvokeOperation invokeOut = context.LogoutUser(OnLogoutCompleted, null);
        }

        private void OnLogoutCompleted(InvokeOperation result)
        {
            if (result.HasError)
            {
                MessageBox.Show("Error Loging Out, try again.");
            }
            else
            {
                NavigationService.Navigate(new Uri("/Views/Login.xaml", UriKind.Relative));

                App current = (App)Application.Current;

                current.UserName = String.Empty;
                current.UserRole = String.Empty;
                current.DisplayName = String.Empty;

                current.CompanyID = 0;
                current.DepartmentID = 0;
                current.EmployeeId = 0;
            }
        }

        //====================================================================
        //--> Methods to Load & Reload Organization Structure Tree:

        private void structureTree_Loaded(object sender, RoutedEventArgs e)
        {
            ReloadTreeHandler(sender, new EventArgs());
        }

        public void ReloadTreeHandler(object sender, EventArgs e)
        {
            AttendanceServiceClient proxy = General.General.GetProxy();

            proxy.BuildStructureCompleted += OnBuildStructureCompleted;

            proxy.BuildStructureAsync(((App)Application.Current).UserRole, DateTime.Now);
        }

        public void OnBuildStructureCompleted(object sender, BuildStructureCompletedEventArgs e)
        {
            structureTree.ItemsSource = e.Result;

            ExpandStructureTree(e.Result);
        }

        //--> Method to expand the whole Structure Tree after loading it:
        public void ExpandStructureTree(ObservableCollection<TreeNode> roots)
        {
            structureTree.UpdateLayout();

            foreach (TreeNode parent in roots)
            {
                TreeViewItem parentNode = (TreeViewItem)structureTree.ItemContainerGenerator.ContainerFromItem(parent);

                parentNode.IsExpanded = true;

                foreach (var child in parentNode.Items)
                {
                    parentNode.UpdateLayout();

                    TreeViewItem childNode = (TreeViewItem)parentNode.ItemContainerGenerator.ContainerFromItem(child);

                    childNode.IsExpanded = true;
                }
            }
        }

        //--> Filter Employees when Structure Tree Node Selection Changed:
        private void structureTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            TreeNode currNode = (TreeNode)e.NewValue;

            if (currNode != null)
            {
                App myApp = (App)Application.Current;

                myApp.CompanyID = currNode.CompanyID;

                myApp.DepartmentID = currNode.DepartmentID;
                myApp.EmployeeId = currNode.EmployeeId;

                myApp.InvokeChangeEmployeesEvent(sender, new EventArgs());

                myApp.RefreshStatistics(sender, new EventArgs());
            }
        }

        //====================================================================
        //--> Event Handlers for Adding, Editting, and Deleting Companyies:

        public void NewCompanyHandler(object sender, EventArgs e)
        {
            CompanyEdit compedit = new CompanyEdit("New Company");

            compedit.LoadData(No.Zero);
            compedit.Closed += TreeItemEditWindow_Closed;

            compedit.Show();
        }

        public void EditCompanyHandler(object sender, EventArgs e)
        {
            App myApp = (App)Application.Current;

            CompanyEdit compedit = new CompanyEdit("Edit Company");

            compedit.LoadData(myApp.CompanyID.Value);
            compedit.Closed += TreeItemEditWindow_Closed;

            compedit.Show();
        }

        public void DeleteCompanyHandler(object sender, EventArgs e)
        {
            App myApp = (App) Application.Current;

            if (MessageBox.Show(ApplicationStrings.DeleteMessage, ApplicationStrings.Delete
                , MessageBoxButton.OKCancel) == MessageBoxResult.OK)
            {
                context.DestroyCompanyById(myApp.CompanyID.Value, OnDeleteTreeItemCompleted, null);
            }
        }

        //====================================================================
        //--> Event Handlers for Adding, Editting, and Deleting Departments:

        public void NewDepartmentHandler(object sender, EventArgs e)
        {
            DepartmentEdit newDepartment = new DepartmentEdit("New Department");

            newDepartment.LoadData(No.Zero);
            newDepartment.Closed += TreeItemEditWindow_Closed;

            newDepartment.Show();
        }

        public void EditDepartmentHandler(object sender, EventArgs e)
        {
            App myApp = (App)Application.Current;

            DepartmentEdit editDepartment = new DepartmentEdit("Edit Department");

            editDepartment.LoadData(myApp.DepartmentID.Value);
            editDepartment.Closed += TreeItemEditWindow_Closed;

            editDepartment.Show();
        }

        public void DeleteDepartmentHandler(object sender, EventArgs e)
        {
            App myApp = (App)Application.Current;

            if (MessageBox.Show(ApplicationStrings.DeleteMessage, ApplicationStrings.Delete
                , MessageBoxButton.OKCancel) == MessageBoxResult.OK)
            {
                context.DestroyDepartmentById(myApp.DepartmentID.Value, OnDeleteTreeItemCompleted, null);
            }
        }

        public void OnDeleteTreeItemCompleted(InvokeOperation result)
        {
            ReloadTreeHandler(null, new EventArgs());
        }

        public void TreeItemEditWindow_Closed(object sender, EventArgs e)
        {
            ReloadTreeHandler(null, e);
        }

        //====================================================================
        //--> Common Event Handlers for 'New', 'Edit', and 'Delete' Links:

        private void NewRecordLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.InvokeAddEvent(sender, e);
        }

        private void EditRecordLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.InvokeEditEvent(sender, e);
        }

        private void DeleteRecordLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.InvokeDeleteEvent(sender, e);
        }

        //====================================================================
        //--> 'New', 'Edit', and 'Delete' Punches:

        private void taskDion_Loaded(object sender, RoutedEventArgs e)
        {
            EmpHoursItem.IsSelected = true;
        }

        private void EmpHoursItem_Selected(object sender, RoutedEventArgs e)
        {
            mainFrame.Navigate(new Uri("/Views/EmployeeHours.xaml", UriKind.Relative));
        }

        //====================================================================
        //--> 'New', 'Edit', and 'Delete' Jobs:

        private void JobsItem_Selected(object sender, RoutedEventArgs e)
        {
            mainFrame.Navigate(new Uri("/Views/Jobs.xaml", UriKind.Relative));
        }

        //====================================================================
        //--> 'New', 'Edit', and 'Delete' Users:

        private void UsersItem_Selected(object sender, RoutedEventArgs e)
        {
            mainFrame.Navigate(new Uri("/Views/Users.xaml", UriKind.Relative));
        }

        //====================================================================
        //--> 'New', 'Edit', and 'Delete' Shifts:

        private void ShiftsItem_Selected(object sender, RoutedEventArgs e)
        {
            mainFrame.Navigate(new Uri("/Views/Shifts.xaml", UriKind.Relative));

            ChangeShiftLinksStatus(true);
        }

        private void ShiftsLink_Click(object sender, RoutedEventArgs e)
        {
            ChangeShiftLinksStatus(true);
        }

        private void ShitAssignmentsLink_Click(object sender, RoutedEventArgs e)
        {
            ChangeShiftLinksStatus(false);
        }

        private void ChangeShiftLinksStatus(bool status)
        {
            NewShiftLink.IsEnabled = status;
            EditShiftLink.IsEnabled = status;
            DeleteShiftLink.IsEnabled = status;

            NewShiftAssignLink.IsEnabled = !status;
            EditShiftAssignLink.IsEnabled = !status;
            DeleteShiftAssignLink.IsEnabled = !status;
        }

        //====================================================================
        //--> 'New', 'Edit', and 'Delete' Exceptions:

        private void ExceptionsItem_Selected(object sender, RoutedEventArgs e)
        {
            mainFrame.Navigate(new Uri("/Views/Exceptions.xaml", UriKind.Relative));

            ChangeExceptionLinksStatus(true);
        }

        private void ExceptionsLink_Click(object sender, RoutedEventArgs e)
        {
            ChangeExceptionLinksStatus(true);
        }

        private void ExAssignmentsLink_Click(object sender, RoutedEventArgs e)
        {
            ChangeExceptionLinksStatus(false);
        }

        private void ChangeExceptionLinksStatus(bool status)
        {
            NewExceptionLink.IsEnabled = status;
            EditExceptionLink.IsEnabled = status;
            DeleteExceptionLink.IsEnabled = status;

            NewExAssignmentsLink.IsEnabled = !status;
            EditExAssignLink.IsEnabled = !status;
            DeleteExAssignLink.IsEnabled = !status;
        }

        //====================================================================
        //--> 'New', 'Edit', and 'Delete' Companyies:

        private void StructureItem_Selected(object sender, RoutedEventArgs e)
        {
            mainFrame.Navigate(new Uri("/Views/Employees.xaml", UriKind.Relative));
        }

        private void NewComLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.InvokeAddCompanyEvent(sender, new EventArgs());
        }

        private void EditComLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.InvokeEditCompanyEvent(sender, new EventArgs());
        }
        
        private void DeleteComLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.InvokeDeleteCompanyEvent(sender, new EventArgs());
        }

        //====================================================================
        //--> 'New', 'Edit', and 'Delete' Departments:

        private void NewDepLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.InvokeAddDepartmentEvent(sender, new EventArgs());
        }

        private void EditDepLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.InvokeEditDepartmentEvent(sender, new EventArgs());
        }

        private void DeleteDepLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.InvokeDeleteDepartmentEvent(sender, new EventArgs());
        }

        //====================================================================
        //--> 'New', 'Edit', and 'Delete' Locations:

        private void LocationsItem_Selected(object sender, RoutedEventArgs e)
        {
            mainFrame.Navigate(new Uri("/Views/Locations.xaml", UriKind.Relative));
        }

        //====================================================================
        //--> Event Handler for 'Company' Details:

        private void ComDetailsLink_Click(object sender, RoutedEventArgs e)
        {
            CompanyDetails comDetails = new CompanyDetails();

            comDetails.LoadData(((App)Application.Current).CompanyID.Value);

            comDetails.Show();
        }

        private void EmpDetailsLink_Click(object sender, RoutedEventArgs e)
        {
            if (((App) Application.Current).EmployeeId > 0)
            {
                EmployeeDetails empDetails = new EmployeeDetails();

                empDetails.Show();
            }
        }

        //====================================================================
        //--> TreeView Template Handler to change Global Company ID according
        //    to user selection in Structure Tree.

        private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            TextBlock block = sender as TextBlock;

            TreeNode node = block.DataContext as TreeNode;

            App myApp = (App)Application.Current;

            if (node != null)
            {
                if (myApp.CompanyID.Value != node.CompanyID)
                {
                    myApp.CompanyID = node.CompanyID;
                }

                if (myApp.DepartmentID.Value != node.DepartmentID)
                {
                    myApp.DepartmentID = node.DepartmentID;
                }
            }
        }

        //====================================================================
        //--> Event Handlers for 'Settings' Accordion Item:

        private void SettingsItem_Selected(object sender, RoutedEventArgs e)
        {
            mainFrame.Navigate(new Uri("/Views/AccountingPeriod.xaml", UriKind.Relative));
        }

        //====================================================================
        //--> Apply Accounting Period:

        private void applyPeriodButton_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.PeriodFrom = PeriodFrom.SelectedDate.Value;
            myApp.PeriodTo = PeriodTo.SelectedDate.Value;
        }

        //====================================================================

        private void ReportsItem_Selected(object sender, RoutedEventArgs e)
        {
            mainFrame.Navigate(new Uri("/Views/Reports.xaml", UriKind.Relative));
        }

        private void SummaryCardRepLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.ReportName = "Summary Time Card Report";
        }

        private void DetailedCardRepLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.ReportName = "Detailed Time Card Report";
        }

        private void DetailedOvertimeRepLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.ReportName = "Detailed Overtime Report";
        }

        private void ShiftAssignmentRepLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.ReportName = "Shift Assignments Report";
        }

        private void ExAssignmentRepLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.ReportName = "Exception Assignments Report";
        }

        private void OnSiteRepLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.ReportName = "OnSite Presence Report";
        }

        private void LateComerRepLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.ReportName = "Late Comers Report";
        }

        private void AbsenceRepLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.ReportName = "Absence Report";
        }

        private void SavedHoursRepLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.ReportName = "Saved Hours Report";
        }

        private void MissingPunchRepLink_Click(object sender, RoutedEventArgs e)
        {
            App myApp = (App)Application.Current;

            myApp.ReportName = "Missing Punches Report";
        }

        //====================================================================
        //--> Show Window with Employees who came to work today and those who
        //    didn't came to work yet.

        //--> Refresh Numbers:
        private void AttendanceButton_Click(object sender, RoutedEventArgs e)
        {
            ReloadTreeHandler(null, new EventArgs());

            GetAttendanceStatistics();
        }

        //--> Show Employee who came today till this moment.
        private void AttendantsBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            TodayAttendants todayAttendants = new TodayAttendants();

            todayAttendants.Show();
        }

        //--> Show Employees who didn't make it today till this moment.
        private void AbsenteeBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            TodayAbsence todayAbsence = new TodayAbsence();

            todayAbsence.Show();
        }

        private void RefreshStatisticsHandler(object sender, EventArgs e)
        {
            GetAttendanceStatistics();
        }

        private void GetAttendanceStatistics()
        {
            context.CountAttendantsNumber(((App)Application.Current).CompanyID == null
                    ? 0 : ((App)Application.Current).CompanyID.Value
                , DateTime.Now, OnAttendantsCountCompleted, null);
        }

        private void OnAttendantsCountCompleted(InvokeOperation result)
        {
            if (result.HasError)
            {
                result.MarkErrorAsHandled();
                MessageDisplay message = new MessageDisplay(ApplicationStrings.GeneralError
                    , ApplicationStrings.GeneralError, "Error");
                message.Show();
            }
            else
            {
                string[] numbers = result.Value.ToString().Split('|');

                AttendantsBlock.Content = numbers[0];

                AbsenteeBlock.Content = numbers[1];
            }
        }
    }
}